package tk.winshu.shortestpath.model;

import java.awt.*;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author winshu
 * @date 2015年2月2日
 */
public class Node extends NObject {

    private static final int NONE_INDEX = 0;

    /**
     * 终点指向当前节点的节点集
     * <p>
     * startNodes -> current
     */
    private List<Node> startNodes;
    /**
     * 起点为当前节点的节点集
     * <p>
     * current -> endNodes
     */
    private List<Node> endNodes;

    private boolean isVisible;

    /**
     * 默认构造方法，导入时需要
     */
    public Node() {
        this(NONE_INDEX, 0, 0);
    }

    public Node(int index, Point2D point) {
        this(index, point.getX(), point.getY());
    }

    public Node(int index, double x, double y) {
        super(index, x, y);
        this.startNodes = new ArrayList<>();
        this.endNodes = new ArrayList<>();
        this.isVisible = true;
    }

    public boolean relationTo(Node endNode) {
        if (endNodes.contains(endNode) || endNode.startNodes.contains(this)) {
            return false;
        }
        // 相互建立关系
        this.endNodes.add(endNode);
        endNode.startNodes.add(this);
        return true;
    }

    /**
     * 清除与其他节点的关系
     */
    public void cleanRelations() {
        // 移除另一端节点的关系
        startNodes.forEach(target -> target.endNodes.remove(this));
        endNodes.forEach(target -> target.startNodes.remove(this));
        // 清空自身关系
        startNodes.clear();
        endNodes.clear();
    }

    /**
     * 判断是否与另一节点有连线关系
     */
    private boolean hasRelation(Node node) {
        return startNodes.contains(node) || endNodes.contains(node);
    }

    /**
     * 计算到另一节点的距离
     */
    public double distanceTo(Node other) {
        if (hasRelation(other)) {
            return Point2D.distance(getLocation().getX(), getLocation().getY(), other.getLocation().getX(), other.getLocation().getY());
        }
        return Integer.MAX_VALUE;
    }

    /**
     * 获取所有的连线节点
     */
    public List<Node> getAllRelations() {
        List<Node> allNodes = new ArrayList<>(startNodes);
        allNodes.addAll(endNodes);
        return allNodes;
    }

    /**
     * 获取所有起点，不可修改
     */
    public List<Node> getStartNodes() {
        return Collections.unmodifiableList(startNodes);
    }

    /**
     * 获取所有终点
     */
    public List<Node> getEndNodes() {
        return Collections.unmodifiableList(endNodes);
    }

    /**
     * 移除一个连线关系
     */
    public void releaseRelation(Node node) {
        startNodes.remove(node);
        endNodes.remove(node);
        node.startNodes.remove(this);
        node.endNodes.remove(this);
    }

    @Override
    public String toString() {
        return String.format("Node<%d>", getIndex());
    }

    /**
     * 绘制节点
     */
    public void draw(Graphics2D g2d, NodeStatus nodeStatus) {
        super.draw(g2d, nodeStatus.getImage(), nodeStatus.getColor(), nodeStatus.isDrawShape());
    }

    public boolean isVisible() {
        return isVisible;
    }

    public void setVisible(boolean isVisible) {
        this.isVisible = isVisible;
    }
}
